package yc.tool.dbmigrate.service;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import yc.tool.dbmigrate.common.Constant;
import yc.tool.dbmigrate.conf.SyncPropConfigurer;
import yc.tool.dbmigrate.dao.CommonDao;
import yc.tool.dbmigrate.entity.SyncBean;
import yc.tool.dbmigrate.entity.SyncConfig;

@Component
public class MigreateCore {
//	private final Logger log = Logger.getLogger(this.getClass());
	private final Logger log = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private CommonDao commonDao;
	
//	@Resource(name="jdbcTemplate_s")
//    private JdbcTemplate jdbcTemplate_s;
//	
	@Resource(name="jdbcTemplate_o")
    private JdbcTemplate jdbcTemplate_o;
//	
//	@Resource(name="jdbcTemplate_m")
//    private JdbcTemplate jdbcTemplate_m;
//	
//	@Autowired
//	private SqlHandler sqlHandler;
//	
//	//-------------------------------------------------------测试---------------------------------------------------------------//
//	public void test() {
//		System.out.println("-------------test-----");
//		log.info("测试log{}", "参数");
//	}
//	
//	/**
//	 * 测试查询Sqlserver
//	 */
//	public void testSelectSqlserver() {
//		String sql = "select accountId, realName from account where accountId=101";
//		List<Map<String, Object>> list = jdbcTemplate_s.queryForList(sql);
//		Map<String, Object> map = list.get(0);
//		System.out.println(map.get("accountId") + "-" + map.get("realName"));
//		
//	}
//	
//	/**
//	 * 测试查询oracle
//	 */
//	public void testSelectOracl() {
//		String sql = "select accountId, realName from account where accountId=101";
//		List<Map<String, Object>> list = jdbcTemplate_o.queryForList(sql);
//		Map<String, Object> map = list.get(0);
//		System.out.println(map.get("accountId") + "-" + map.get("realName"));
//	}
//	/**
//	 * 测试新增数据
//	 */
//	@Transactional("txManager_o")
//	public void testInsertOracl() {
//		log.info("----测试新增数据");
//		String sql = "insert into account(accountId, realName, tenantCode, active, leftTime, status) values(106, 'ccc', 1, 1, 1, 1)";
//		try {
//			jdbcTemplate_o.execute(sql);
//		}catch(Exception e) {
//			log.info("插入出错", e);
//		}
//		
//		log.info("----over");
//	}
	
	/**
	 * 测试批量插入数据
	 */
	@Transactional("txManager_o")
	public void testBatInster() {
		String sql = "insert into account(accountId, realName, tenantCode, active, leftTime, status) values(?, ?, ?, ?, ?, ?)";
		List<Object[]> dataSet = new ArrayList<>();
		dataSet.add(new Object[] {102, "aaa", 1, 1, 1, 1});
		dataSet.add(new Object[] {103, "bbb", 1, 1, 1, 1});
		dataSet.add(new Object[] {104, "ccc", 1, 1, 1, 1});
		
		int[] res = jdbcTemplate_o.batchUpdate(sql, new BatchPreparedStatementSetter() {

			@Override
			public void setValues(PreparedStatement ps, int i) throws SQLException {
				Object[] obj = dataSet.get(i);
				ps.setInt(1, Integer.parseInt(obj[0].toString()));
				ps.setString(2, obj[1].toString());
				ps.setInt(3, Integer.parseInt(obj[2].toString()));
				ps.setInt(4, Integer.parseInt(obj[3].toString()));
				ps.setInt(5, Integer.parseInt(obj[4].toString()));
				ps.setInt(6, Integer.parseInt(obj[5].toString()));
//				ps.setBigDecimal(parameterIndex, x);//大数字
//				ps.setBytes(parameterIndex, x);//blob等二进制
//				ps.setDate(parameterIndex, x);//日期
//				ps.setDouble(parameterIndex, x);//浮点数
//				ps.setInt(parameterIndex, x);//整数
//				ps.setLong(parameterIndex, x);//长整形
//				ps.setTimestamp(parameterIndex, x);//时间戳
				
			}

			@Override
			public int getBatchSize() {
				return dataSet.size();
			}
			
		});
		for (int i : res) {
			System.out.println(i);
		}

		
		
	}
//	
//	
//	/**
//	 * 测试从sqlserver查数据，然后倒入oracle
//	 */
//	@Transactional("txManager_o")
//	public void testSqlserverToOracle() {
//		//查询sqlserver
//		String sql_s = "select accountId, realName, tenantCode, active, leftTime, status from account where accountId=105";
//		List<Map<String, Object>> list = jdbcTemplate_s.queryForList(sql_s);
//		Map<String, Object> map = list.get(0);
//		System.out.println(">>>>>" + map.get("accountId") + "-" + map.get("realName"));
//		
//		
//		//插入oracle
//		String sql_o = "insert into account(accountId, realName, tenantCode, active, leftTime, status) "
//				+ "values(" + map.get("accountId") + ", '" + map.get("realName") + "', " + 
//				map.get("tenantCode") + ", " + map.get("active") + ", " + map.get("leftTime") + ", " + map.get("status") + ")";
//		jdbcTemplate_o.execute(sql_o);
//	}
	
	//----------------------------------------------------------------------------------------------------------------------//
	
	
	//多线程变慢了。。。
//	private List<Integer> taskResult = null;//任务集合，下标表示配置中的sync-index，值表示（0成功，1失败）
	private Long startTime = null;
	
	/**
	 * 数据迁移主方法
	 */
	public void dbMigrate() {
		startTime = System.currentTimeMillis();
		SyncConfig syncConfig = SyncPropConfigurer.getSyncConfig();;
		List<SyncBean> syncBeans = syncConfig.getSyncBeans();
		
//		ExecutorService threadPool = Executors.newCachedThreadPool();
//		
//		taskResult = new ArrayList<Integer>(syncBeans.size()+1);
//		taskResult.add(0);//配置中任务从1开始，这个list的下标对应任务编号，第0个默认为0
//		for (int i = 1; i < syncBeans.size(); i++) {
//			taskResult.add(null);
//		}
		
		for (SyncBean syncBean : syncBeans) {
			if ("simple".equals(syncBean.getSyncType())) {
				simpleDbMigrate(syncBean);
			} else if ("custom".equals(syncBean.getSyncType())) {
				
				try {
					ICustomSyncService cus = (ICustomSyncService) Class.forName(syncBean.getClassName()).newInstance();
					cus.start();
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InstantiationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
//			threadPool.submit(new SyncBeanTask(syncBean));
		}
		
		log.info("同步结束，总共用时：" + (System.currentTimeMillis()-startTime) + "毫秒");
		
	}
	
	/**
	 * 执行每个同步任务
	 * @author yuancan
	 * 返回 map<任务index，是否成功>   0成功   1失败
	 */
//	class SyncBeanTask implements Callable<Map<Integer, Integer>> {
//		private final Logger log = LoggerFactory.getLogger(this.getClass());
//		
//		private SyncBean syncTask;
//		public SyncBeanTask(SyncBean syncBean) {
//			syncTask = syncBean;
//		}
//
//		@Override
//		public Map<Integer, Integer> call() throws Exception {
//			Map<Integer, Integer> res = new HashMap<>();
//			try {
//				while(taskResult.get(syncTask.getParent()) == null) {
//					Thread.sleep(2000);//如果上级节点还没结果，就继续等2秒
//				}
//				if (taskResult.get(syncTask.getParent()) == 0) {
//					log.info("任务{}开始", syncTask.getSyncIndex());
//					if ("simple".equals(syncTask.getSyncType())) {
//						simpleDbMigrate(syncTask);
//					}
//				}
//				
//			} catch (Exception e) {
//				res.put(syncTask.getSyncIndex(), 1);
//				taskResult.set(syncTask.getSyncIndex(), 1);
//				log.info("任务{}同步失败", syncTask.getSyncIndex());
//				return res;
//			}
//			res.put(syncTask.getSyncIndex(), 0);
//			taskResult.set(syncTask.getSyncIndex(), 0);
//			log.info("任务{}同步成功", syncTask.getSyncIndex());
//			
//			if (!taskResult.contains(null)) {
//				log.info("同步结束，总共用时：{}秒", (System.currentTimeMillis()-startTime)/1000);
//			}
//			return res;
//		}
//		
//	}
	
	/**
	 * 简单数据迁移(一张表)
	 * @param syncBean
	 */
	private void simpleDbMigrate(SyncBean syncBean) {
		//总页数
		Integer total = commonDao.getTotal(syncBean.getTableInfo());
		Integer totalPageNumber = (total / Constant.PageSize) + 1;
		log.info("开始同步第" + syncBean.getSyncIndex() + "模块, 简单表同步：" + syncBean.getTableInfo().getSourceTableName() + ", 每页" + Constant.PageSize + ", 共" + totalPageNumber + "页，总共" + total + "条数据");
		
		//循环查询并插入数据
		for (int i = 0; i < totalPageNumber; i++) {
			List<Map<String, Object>> res = commonDao.selectPageData(syncBean.getTableInfo(), (i+1));
			log.info("第" + syncBean.getSyncIndex() + "模块，第" + (i+1) + "/" + totalPageNumber + "页 有" + res.size() + "条数据");
			if (null == res || res.size() == 0) {
				break;
			}
			commonDao.insertBatData(syncBean.getTableInfo(), res);
//			int wrongnum = commonDao.insertData(syncBean.getTableInfo(), res);
//			if (wrongnum > 10) {
//				log.info("模块{}，第{}页同步失败，终止同步", syncBean.getSyncIndex(), (i+1));
//				throw new DbException("同步失败超过10条数据，同步终止");
//			}
		}
		
	}

	
}
